import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map.Entry;
import java.util.Stack;
import java.util.TreeSet;

public class State {

	Hashtable<Integer, Variable> variables = new Hashtable<Integer, Variable>();
	Stack<Action> possible;
	// ArrayList<Integer> done = new ArrayList<Integer>();
	String done = "";
	int hash = 0;
	ArrayList<String> values2;

	public int hashCode() {
		if (hash == 0) {
			TreeSet<Integer> ts = new TreeSet<Integer>(variables.keySet());
			return ts.toString().hashCode();
		} else {
			return hash;
		}
	}

	public boolean equals(Object o) {

		// return o.hashCode() == hashCode();

		State s = (State) o;
		// boolean equals = true;
		for (int v : s.variables.keySet()) {
			if (!variables.containsKey(v)) {
				return false;
			}
		}
		return true;
		/*
		 * boolean jest =false; if (getVariables(v.name) != null) { for
		 * (Variable v2 : getVariables(v.name)) { boolean spelnia = true; for
		 * (int i = 0; i < v2.values.size(); i++) { if
		 * (!v2.values.get(i).equals(v.values.get(i))) { spelnia= false; } }
		 * if(spelnia){ jest=true; } } } if(!jest){ equals=false; } }
		 * if(equals){ System.out.println(hashCode()+" "+o.hashCode()); } return
		 * equals;
		 * 
		 * /* for (Variable v : variables) { if (s.getVariables(v.name) != null)
		 * { for (Variable v2 : s.getVariables(v.name)) { for (int i = 0; i <
		 * v2.values.size(); i++) { if
		 * (!v2.values.get(i).equals(v.values.get(i))) { return false; } } } } }
		 */

	}

	/*
	 * public ArrayList<Variable> getVariables(int name) { ArrayList<Variable>
	 * wyn = new ArrayList<Variable>(); for (Variable v : variables) { if
	 * (name==v.name) { wyn.add(v); } } return wyn.size() == 0 ? null : wyn; }
	 */

	public State copy() {
		State wyn = new State();
		wyn.variables = new Hashtable<Integer, Variable>();
		wyn.done = done;// new ArrayList<Integer>();
		/*
		 * for (int a : done) { wyn.done.add(a); }
		 */
		for (Entry<Integer, Variable> v : variables.entrySet()) {
			wyn.variables.put(v.getKey(), v.getValue().copy());
		}
		return wyn;
	}

	public State action() {
		// System.out.println(hashCode());
		Action a = possible.pop();
		// System.out.println(a);
		State wyn = copy();
		wyn.done += a.toString() + '\n';
		for (Entry<Integer, Variable> e : a.post.variables.entrySet()) {
			Variable v = e.getValue();
			if (!v.positive) {
				wyn.variables.remove(e.getKey());
				/*
				 * ArrayList<Variable> v2 = wyn.getVariables(v.name); for
				 * (Variable v3 : v2) { for (int i = 0; i < v3.values.size();
				 * i++) { if (v.values.get(i).equals(v3.values.get(i))) {
				 * wyn.variables.remove(v3); } } }
				 */
			} else {
				wyn.variables.put(e.getKey(), v);
			}
		}
		return wyn;
	}

	public ArrayList<String> getValues() {
		if (values2 != null) {
			return values2;
		} else {
			HashSet<String> hs = new HashSet<String>();
			for (Entry<Integer, Variable> e : variables.entrySet()) {
				for (String i : e.getValue().values) {
					if (i.charAt(0) < 97) {
						hs.add(i);
					}
				}
			}
			values2 = new ArrayList<String>(hs);
			return values2;
		}
	}

	public String toString() {
		return variables.toString();
	}

}
